package hero

import (
	"fmt"
	log2 "github.com/name5566/leaf/log"
	"go.mongodb.org/mongo-driver/bson"
	"server/db"
)

type HeroDao struct {
	db *db.MongoMiddleware
}

// Constants
const (
	TBL_HERO = "t_hero"
	// Max allowed data per query
	DATA_MAX_IN = 100
)

func NewHeroDao() *HeroDao {
	return &HeroDao{
		db: db.Db,
	}
}

func (h *HeroDao) GetHeroesByUidStatus(uid string, status int) {
	query := bson.M{"uid": uid}
	var result THero
	err := h.db.FindOne(TBL_HERO, query, &result)
	if err != nil {
		log2.Error("err message is %v", err)
	}
}

// GetHeroesByUid retrieves heroes by user ID
func (h *HeroDao) GetHeroesByUid(uid string) ([]map[string]interface{}, error) {
	var result []map[string]interface{}
	query := bson.M{"uid": uid}
	err := h.db.Find(TBL_HERO, query, &result)
	if err != nil {
		return nil, err
	}

	// Post-process result by mapping 'htid'
	heroesMap := make(map[string]map[string]interface{})
	for _, hero := range result {
		htid := fmt.Sprintf("%v", hero["htid"])
		heroesMap[htid] = hero
	}

	var finalResult []map[string]interface{}
	for _, hero := range heroesMap {
		finalResult = append(finalResult, hero)
	}

	return finalResult, nil
}

// GetHeroByUidHtid retrieves a single hero by user ID and hero type ID
func (h *HeroDao) GetHeroByUidHtid(uid, htid string) (map[string]interface{}, error) {
	var result map[string]interface{}
	query := bson.M{"uid": uid, "htid": htid}
	err := h.db.FindOne(TBL_HERO, query, &result)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// GetArrHeroByHtid retrieves heroes based on a list of hero type IDs
func (h *HeroDao) GetArrHeroByHtid(uid string, arrHtid []string) ([]map[string]interface{}, error) {
	var result []map[string]interface{}
	if len(arrHtid) == 0 {
		return result, nil
	}

	chunks := chunkArray(arrHtid, DATA_MAX_IN)
	var finalResult []map[string]interface{}
	for _, chunk := range chunks {
		query := bson.M{"uid": uid, "htid": bson.M{"$in": chunk}}
		err := h.db.Find(TBL_HERO, query, &result)
		if err != nil {
			return nil, err
		}
		finalResult = append(finalResult, result...)
	}

	// Post-process result by mapping 'htid'
	heroesMap := make(map[string]map[string]interface{})
	for _, hero := range finalResult {
		htid := fmt.Sprintf("%v", hero["htid"])
		heroesMap[htid] = hero
	}

	var processedResult []map[string]interface{}
	for _, hero := range heroesMap {
		processedResult = append(processedResult, hero)
	}

	return processedResult, nil
}

// Helper function to split array into smaller chunks
func chunkArray(arr []string, chunkSize int) [][]string {
	var chunks [][]string
	for i := 0; i < len(arr); i += chunkSize {
		end := i + chunkSize
		if end > len(arr) {
			end = len(arr)
		}
		chunks = append(chunks, arr[i:end])
	}
	return chunks
}
